package o2o.web.actions.cost;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.gson.JsonObject;
import com.jinyou.utils.common.AjaxResult;
import com.jinyou.utils.common.Geohash;
import com.jinyou.utils.common.JYMathDoubleUtils;
import com.jinyou.utils.common.ValidateUtil;
import o2o.cache.agent.CityAgentMemory;
import o2o.cache.agent.ShopAgentRelationMemory;
import o2o.cache.shop.ShopMemory;
import o2o.cache.user.UserAddressMemory;
import o2o.company.service.CompanyService;
import o2o.dao.PO.agent.CityAgent;
import o2o.company.model.ShopInfo;
import o2o.dao.PO.user.UserAddress;
import o2o.dao.VO.cost.CostComputeInfo;
import o2o.company.service.ShopService;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import o2o.system.data.SYS_SETTINGS;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname CostComputeController
 * @Description
 * @Date 2019/5/9 19:46
 * @Created by yangtk
 */
@RestController
public class CostComputeController {
    private final ShopService shopService;
    private final CompanyService companyService;

    public CostComputeController(ShopService shopService, CompanyService companyService) {
        this.shopService = shopService;
        this.companyService = companyService;
    }

    /**
     * 计算费用
     *
     * @return
     */
    @RequestMapping(value = "/compute/delivery/cost", method = RequestMethod.POST)
    public String ComputeDeliveryPrice(CostComputeInfo computeInfo) {
        // 参数校验
        if (computeInfo == null) {
            return AjaxResult.successResult(0 + "");
        }
        if (ValidateUtil.isNotLatLng(computeInfo.getBuyLat(), computeInfo.getBuyLng()) || ValidateUtil.isNotLatLng(computeInfo.getSellLat(), computeInfo.getSellLng())) {
            return AjaxResult.successResult(0 + "");
        }
        if (computeInfo.getWithinDistance() == null || computeInfo.getWithinDistance() == null || computeInfo.getOneKmCost() == null) {
            return AjaxResult.successResult(0 + "");
        }
        // 计算买家和卖家之间的距离
        double distinctShop = Geohash.distance(computeInfo.getBuyLat(), computeInfo.getBuyLng(), computeInfo.getSellLat(), computeInfo.getSellLng());
        // 距离除以1000
        Double distinctRang = JYMathDoubleUtils.div(distinctShop, 1000);
        double delivery = 0.0d;

//        shopService.getById(computeInfo.get)


        // todo 计算配送费用、夜间加价
        if (JYMathDoubleUtils.sub(distinctRang, computeInfo.getWithinDistance()) <= 0) {
            delivery = JYMathDoubleUtils.add(delivery, computeInfo.getFixedCost());
        } else {
            double after = JYMathDoubleUtils.sub(distinctRang, computeInfo.getWithinDistance());
            if (computeInfo.getIsDistanceCeil() != null && computeInfo.getIsDistanceCeil() == 1) {
                after = Math.ceil(after);
            }
            delivery = JYMathDoubleUtils.add(delivery, JYMathDoubleUtils.add(computeInfo.getFixedCost(), JYMathDoubleUtils.mul(after, computeInfo.getOneKmCost())));
        }
        if (computeInfo.getIsWeightCompute() != null && computeInfo.getIsWeightCompute() == 1) {
            // 配送费参与计算
            if (computeInfo.getTotalWeight() == null
                    || computeInfo.getFixedWeightCost() == null
                    || computeInfo.getWithinWeight() == null
                    || computeInfo.getOneKgWeightCost() == null) {
                return AjaxResult.successResult(delivery + "");
            }
            if (JYMathDoubleUtils.sub(computeInfo.getTotalWeight(), computeInfo.getWithinWeight()) <= 0) {
                delivery = JYMathDoubleUtils.add(delivery, computeInfo.getFixedWeightCost());
            } else {
                Double after = JYMathDoubleUtils.sub(computeInfo.getTotalWeight(), computeInfo.getWithinWeight());
                if (computeInfo.getIsWeightCeil() != null && computeInfo.getIsWeightCeil() == 1) {
                    after = Math.ceil(after);
                }
                delivery = JYMathDoubleUtils.add(delivery, JYMathDoubleUtils.add(computeInfo.getFixedWeightCost(), JYMathDoubleUtils.mul(after, computeInfo.getOneKgWeightCost())));
            }
        }

        // 配送费满减
        if (ValidateUtil.isAbsDouble(computeInfo.getFreeYunFei())) {
            if (JYMathDoubleUtils.sub(computeInfo.getFreeYunFei(), computeInfo.getTotalGoodsMoney()) <= 0) {
                // 设置本订单实际收取的配送费
                if (null != computeInfo.getFreeYunFeiMoney()) {
                    if (0 == -1 - computeInfo.getFreeYunFeiMoney()) {
                        //免配送费
                        delivery = 0d;
                    } else {
                        //减配送费
                        delivery = JYMathDoubleUtils.sub(delivery, computeInfo.getFreeYunFeiMoney());
                        if (delivery < 0) {
                            delivery = 0d;
                        }
                    }
                }
            }
        }

        return AjaxResult.successResult(delivery + "");
    }

    @RequestMapping(value = "/compute/delivery/cost/v2", method = RequestMethod.POST)
    public String ComputeDeliveryPriceV2(CostComputeInfo computeInfo) {
        // 如果收货地址不为空，获取买家的经纬度
        if (computeInfo.getDeliveryId() != null && ValidateUtil.isID(computeInfo.getDeliveryId())) {
            UserAddress userAddress = UserAddressMemory.getInstance().getAddressInfo(computeInfo.getDeliveryId());
            if (userAddress == null || ValidateUtil.isNotLatLng(userAddress.getLat(), userAddress.getLng())) {
                if (ValidateUtil.isNotLatLng(computeInfo.getBuyLat(), computeInfo.getBuyLng())) {
                    return AjaxResult.successResult("" + 0);
                }
            } else {
                computeInfo.setBuyLat(userAddress.getLat());
                computeInfo.setBuyLng(userAddress.getLng());
            }
        }
        if (ValidateUtil.isNotLatLng(computeInfo.getBuyLat(), computeInfo.getBuyLng())) {
            return AjaxResult.successResult("" + 0);
        }
        boolean isAgentCompute = false; // 商圈计算方式
        Double distance = 0.0D;
        ShopInfo shopInfo = null;

        // 如果门店ID不为空
        if (ValidateUtil.isNotNull(computeInfo.getShopIds())) {
            // 切割出店铺的ID
            String[] split = computeInfo.getShopIds().split(",");
            Set<Long> shopIdList = Arrays.stream(split).filter(s -> Long.parseLong(s) > 0).map(Long::parseLong).collect(Collectors.toSet());
            if (shopIdList.size() > 1) {
                isAgentCompute = true;
            }
            // 计算每个门店与买家的距离
            Map<Long, Double> shopInfoMap = new HashMap<>();
            shopIdList.forEach(id -> {
                ShopInfo info = ShopMemory.getInstance().getShopById(id);
                if (ValidateUtil.isLatLng(info.getLat(), info.getLng())) {
                    double distinctShop = Geohash.distance(info.getLat(), info.getLng(), computeInfo.getBuyLat(), computeInfo.getBuyLng());
                    shopInfoMap.put(id, distinctShop);
                }
            });
            // 使用最远的位置
            if (!shopInfoMap.isEmpty()) {
                // 找出距离最远的门店ID，使用它的距离
                Long max = getMapValueMax(shopInfoMap);
                if (max != null) {
                    shopInfo = shopService.getById(max);
                    // shopInfo = ShopMemory.getInstance().getShopById(max);
                    distance = shopInfoMap.get(max) == null ? 0.0d : shopInfoMap.get(max);
                }
            }
        } else {
            // 门店ID为空就使用传过来的经纬度
            if (ValidateUtil.isNotLatLng(computeInfo.getSellLat(), computeInfo.getBuyLng())) {
                distance = Geohash.distance(computeInfo.getBuyLat(), computeInfo.getBuyLng(), computeInfo.getSellLat(), computeInfo.getBuyLng());
            } else {
                return AjaxResult.successResult("" + 0);
            }
        }
        // 距离
        if (distance == 0) {
            return AjaxResult.successResult("" + 0);
        }
        // 配送费
        double delivery = 0.0d;
        // 距离/1000, 向上取整
        double distinctRang = Math.ceil(JYMathDoubleUtils.div(distance, 1000));
        // 如果门店不为空且配送费用类型不为空, 执行新逻辑, 否则执行旧逻辑
        if (shopInfo != null && shopInfo.getDeliveryFeeType() != null) {
            try {
                delivery = computeDeliveryPrice3(shopInfo, distinctRang);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        } else {
            // 重量是否参加配送费计算
            boolean is_weight_add_delivery = false;
            if (SYS_SETTINGS.IS_WEIGHT_ADD_DELIVERY != null && SYS_SETTINGS.IS_WEIGHT_ADD_DELIVERY == 1) {
                is_weight_add_delivery = true;
            }
            Double withinDistance = 0.0; //距离 指定距离内收取固定费用
            Double fixedCost = 0.0;// 按单店铺计算：配送固定费用
            Double oneKmCost = 0.0;// 单公里费用：超出指定距离单公里费用
            Double fixedWeightCost = 0.0; //固定重量内价格
            Double withinWeight = 0.0;     // 固定重量内
            Double oneKgWeightCost = 0.0;  // 超出后每kg多少钱
            if (shopInfo != null) {
                withinDistance = shopInfo.getWithinDistance();
                fixedCost = shopInfo.getFixedCost();
                oneKmCost = shopInfo.getOneKmCost();
                Long agentId = ShopAgentRelationMemory.getInstance().getAgentByShopId(shopInfo.getId());
                CityAgent cityAgent = CityAgentMemory.getInstance().getById(agentId);
                if (isAgentCompute) {
                    if (cityAgent == null) {
                        return AjaxResult.successResult("" + 0);
                    }
                    withinDistance = cityAgent.getWithinDistance();
                    fixedCost = cityAgent.getFixedCost();
                    oneKmCost = cityAgent.getOneKmCost();
                    if (is_weight_add_delivery) {
                        fixedWeightCost = cityAgent.getFixedWeightCost();
                        withinWeight = cityAgent.getWithinWeight();
                        oneKgWeightCost = cityAgent.getOneKgWeightCost();
                    }
                } else {
                    // 商圈的
                    if ((withinDistance == null || fixedCost == null || oneKmCost == null)
                            || (withinDistance == 0.0 && fixedCost == 0.0 && oneKmCost == 0.0)) {
                        if (cityAgent == null) {
                            return AjaxResult.successResult("" + 0);
                        }
                        withinDistance = cityAgent.getWithinDistance();
                        fixedCost = cityAgent.getFixedCost();
                        oneKmCost = cityAgent.getOneKmCost();
                    }
                    if ((withinDistance == null || fixedCost == null || oneKmCost == null)
                            || (withinDistance == 0.0 && fixedCost == 0.0 && oneKmCost == 0.0)) {
                        return AjaxResult.successResult("" + 0);
                    }
                    //
                    if (is_weight_add_delivery) {
                        fixedWeightCost = shopInfo.getFixedWeightCost();
                        withinWeight = shopInfo.getWithinWeight();
                        oneKgWeightCost = shopInfo.getOneKgWeightCost();
                        if ((fixedWeightCost == null || withinWeight == null || oneKgWeightCost == null)
                                || (fixedWeightCost == 0.0 && withinWeight == 0.0 && oneKgWeightCost == 0.0)) {
                            if (cityAgent == null) {
                                return AjaxResult.successResult("" + 0);
                            }
                            fixedWeightCost = cityAgent.getFixedWeightCost();
                            withinWeight = cityAgent.getWithinWeight();
                            oneKgWeightCost = cityAgent.getOneKgWeightCost();
                        }
                        if ((fixedWeightCost == null || withinWeight == null || oneKgWeightCost == null)
                                || (fixedWeightCost == 0.0 && withinWeight == 0.0 && oneKgWeightCost == 0.0)) {
                            if (cityAgent == null) {
                                return AjaxResult.successResult("" + 0);
                            }
                        }
                    }
                }
            }
            if ((fixedWeightCost == null || withinWeight == null || oneKgWeightCost == null) || withinDistance == null || fixedCost == null || oneKmCost == null) {
                return AjaxResult.successResult("" + 0);
            }
            if (JYMathDoubleUtils.sub(distinctRang, withinDistance) <= 0) {
                delivery = JYMathDoubleUtils.add(delivery, fixedCost);
            } else {
                double after = JYMathDoubleUtils.sub(distinctRang, withinDistance);
                after = Math.ceil(after);
                delivery = JYMathDoubleUtils.add(delivery, JYMathDoubleUtils.add(fixedCost, JYMathDoubleUtils.mul(after, oneKmCost)));
            }
            if (is_weight_add_delivery) {
                // 配送费参与计算
                if (computeInfo.getTotalWeight() == null) {
                    return AjaxResult.successResult(delivery + "");
                }
                if (JYMathDoubleUtils.sub(computeInfo.getTotalWeight(), withinWeight) <= 0) {
                    delivery = JYMathDoubleUtils.add(delivery, fixedWeightCost);
                } else {
                    Double after = JYMathDoubleUtils.sub(computeInfo.getTotalWeight(), withinWeight);
                    delivery = JYMathDoubleUtils.add(delivery, JYMathDoubleUtils.add(fixedWeightCost, JYMathDoubleUtils.mul(after, oneKgWeightCost)));
                }
            }
        }
        // 配送费满减
        if (shopInfo != null && ValidateUtil.isAbsDouble(shopInfo.getFreeYunFei())) {
            if (JYMathDoubleUtils.sub(shopInfo.getFreeYunFei(), computeInfo.getTotalGoodsMoney()) <= 0) {
                // 设置本订单实际收取的配送费
                if (null != shopInfo.getFreeYunFeiMoney()) {
                    if (0 == -1 - shopInfo.getFreeYunFeiMoney()) {
                        //免配送费
                        delivery = 0d;
                    } else {
                        //减配送费
                        delivery = JYMathDoubleUtils.sub(delivery, shopInfo.getFreeYunFeiMoney());
                        if (delivery < 0) {
                            delivery = 0d;
                        }
                    }
                }
            }
        }
        return AjaxResult.successResult("" + delivery);
    }

    private Double computeDeliveryPrice3(ShopInfo shopInfo, Double distinctRang) throws ParseException {
        // 配送费
        double delivery = 0.0d;
        String deliveryFeeType = shopInfo.getDeliveryFeeType();
        String deliveryFee = shopInfo.getDeliveryFee();
        if (StringUtils.isEmpty(deliveryFeeType)) {
            return delivery;
        }
        /*
         * 配送费用类型 1固定 2按单量收费 3按距离收费
         * 类型1的deliveryFee为数字："5"， 2为对象数组：[{num:5, fee:5}]，  3为数组：[1,2,3]
         */
        switch (deliveryFeeType) {
            case "1":
                delivery = Double.parseDouble(StringUtils.isEmpty(deliveryFee) ? "0" : deliveryFee);
                break;
            case "2":
                // 值为对象数组 [{num:5, fee:5}], 达到 num单，每单收 fee元
                JSONArray jsonArray = JSON.parseArray(deliveryFee);
                if (jsonArray.size() > 0) {
                    // todo 根据结算周期 来
                }
                break;
            case "3":
                // 值为三位数组, xx公里内 xx元，每超出1公里加收 xx元
                jsonArray = JSON.parseArray(deliveryFee);
                if (jsonArray.size() >= 3) {
                    Integer fee1 = jsonArray.getInteger(0);
                    delivery += JYMathDoubleUtils.add(delivery, jsonArray.getInteger(1));
                    if (distinctRang > fee1) {
                        double sub = JYMathDoubleUtils.sub(distinctRang, fee1);
                        delivery += JYMathDoubleUtils.mul(sub, jsonArray.getInteger(2));
                    }
                }
                break;
        }
        // 夜间加价
        if(shopInfo.getNightPriceType() != null && "1".equals(shopInfo.getNightPriceType())) {
            // JSON数组, 长度3, xx时分 至 xx时分 每单加收 x 元
            String nightPrice = shopInfo.getNightPrice();
            JSONArray jsonArray = JSON.parseArray(nightPrice);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
            if (jsonArray.size() >= 3) {
                // 将时分转成日期
                Date startTime = simpleDateFormat.parse(jsonArray.getString(0));
                Date endTime = simpleDateFormat.parse(jsonArray.getString(1));
                // 当前时间
                Date now = simpleDateFormat.parse(simpleDateFormat.format(new Date()));
                Calendar date = Calendar.getInstance();
                date.setTime(now);
                // 开始时间
                Calendar begin = Calendar.getInstance();
                begin.setTime(startTime);
                // 结束时间
                Calendar end = Calendar.getInstance();
                end.setTime(endTime);
                // 判断当前时间是否在范围内
                if (date.after(begin) && date.before(end)) {
                    String price = jsonArray.getString(2);
                    delivery = JYMathDoubleUtils.add(delivery, Double.parseDouble(StringUtils.isEmpty(price) ? "0" : price));
                }
            }
        }
        return delivery;
    }


    private static Long getMapValueMax(Map<Long, Double> map) {
        if (map == null) {
            return null;
        }
        Double dis = -1d;
        Long id = null;
        int index = 0;
        for (Long tId : map.keySet()) {
            Double dDis = map.get(tId);

            if (index == 0) {
                id = tId;
                dis = dDis;
            } else {
                if (dDis != null && dDis > dis) {
                    id = tId;
                    dis = dDis;
                }
            }
            index++;
        }
        return id;
    }


    public static void main(String[] args) {
        System.out.println(Geohash.distance(36.6937440, 117.1077350, 36.6939200, 117.1075040));
    }

}
